import type { ITask } from '../type'

/**
 * 任务队列类
 */
class TaskQueue {
  // 定义一个私有变量queue，用于存储任务队列
  private queue: ITask<any>[] = []
  // 定义一个私有变量activeTaskNum，用于记录当前正在执行的任务数量
  private activeTaskNum = 0
  /**
   * 任务队列类构造函数
   * @param limit 任务队列的最大长度，默认为5
   * @param debug 是否开启调试模式，默认为false
   */
  constructor(
    private limit = 5,
    public debug = false
  ) {
    // 如果limit小于1，抛出错误
    if (limit < 1) {
      throw new Error('limit must be greater than 1')
    }
  }

  /**
   * 添加任务到队列中
   * @param task 任务对象，包含任务名称和任务函数
   */
  async add<T>(task: ITask<T>) {
    // 如果任务有名称，则使用任务名称，否则使用函数名称或者队列长度
    task.name ? task.name : task.func.name || this.queue.length || ''
    // 将任务添加到队列中
    this.queue.push(task)
    // 执行任务
    await this.run()
  }

  // 执行任务
  private async run() {
    // 当正在执行的任务数量小于限制且队列中有任务时，执行任务
    while (this.activeTaskNum < this.limit && this.queue.length > 0) {
      // 从队列中取出一个任务
      const task = this.queue.shift()
      // 将正在执行的任务数量加1
      this.activeTaskNum++
      // 执行任务
      await this.execute(task!)
    }
  }

  // 执行任务
  private async execute<T>(task: ITask<T>) {
    // 打印正在执行的任务名称
    this.log(`running ${task.name}`)
    try {
      // 执行任务函数
      const result_1 = await task.func()
      // 打印任务执行完成
      this.log(`task ${task.name} done`)
      // 返回任务结果
      return result_1
    } catch (err) {
      // 打印任务执行失败
      this.log(`task ${task.name} failed`)
      throw err
    } finally {
      this.activeTaskNum--
      this.run()
    }
  }

  // 定义一个log方法，用于输出日志信息
  private log(msg: string) {
    // 如果debug为true，则输出日志信息
    if (this.debug) {
      console.info(`[TaskQueue] ${msg}`)
    }
  }
}

export default TaskQueue
